#include "ej_bsp_iis.h"
/* board include*/
#include "board_includes.h"
#include "common_includes.h"

/* private define -------------------------------------------------------- */
typedef struct
{
    void *hw_alink;                         //iis 模块配置句柄
    void *alink_ch[4];                      //iis 数据通道配置句柄
    iis_datas_cbfn_t iis_cbfn[4];
}I2sMoudleInfo_t;

/* private function prototypes ---------------------------------------------- */


/* private variables -------------------------------------------------------- */
ALINK_PARM iis_data = {
    .module = ALINK0,
    .mclk_io = NO_CONFIG_PORT,
    .sclk_io = IO_PORTC_00,
    .lrclk_io = IO_PORTC_01,
#if UCFG_IIS_CH0_EN
	.ch_cfg[0].data_io = IO_PORTC_02,
	.ch_cfg[1].data_io = IO_PORTC_03,
#else
    .ch_cfg[0].data_io = NO_CONFIG_PORT,
    .ch_cfg[1].data_io = NO_CONFIG_PORT,
#endif

#if UCFG_IIS_CH1_EN
    .ch_cfg[2].data_io = NO_CONFIG_PORT,
    .ch_cfg[3].data_io = NO_CONFIG_PORT,
#else
    .ch_cfg[2].data_io = NO_CONFIG_PORT,
    .ch_cfg[3].data_io = NO_CONFIG_PORT,
#endif

    .mode = ALINK_MD_IIS,
#if UCFG_IIS_MODE
    .role = ALINK_ROLE_SLAVE,
#else
    .role = ALINK_ROLE_MASTER,
#endif /*TCFG_IIS_MODE*/
    .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE,
    .bitwide = ALINK_LEN_16BIT,
    .sclk_per_frame = ALINK_FRAME_32SCLK,
	.dma_len = 1 * 1024,
    .sample_rate = UCFG_IIS_SAMPLE_RATE,
    .buf_mode = ALINK_BUF_CIRCLE,
    .iperiod = 64, //配置该项可以控制输入的延时
};

static I2sMoudleInfo_t I2sMoudle;

/* private function ---------------------------------------------- */

#if UCFG_IIS_CH0_EN
static void iis_handle_tx1(void *priv, s16 *buf, u16 len)
{
    struct alnk_hw_ch *hw_channel_parm = *(struct alnk_hw_ch **)priv;
    if(hw_channel_parm == NULL)
	{
        return;
    }

	if (hw_channel_parm->ch_idx < sizeof(I2sMoudle.iis_cbfn)/sizeof(I2sMoudle.iis_cbfn[0]) &&
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx])
	{
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx](buf, len);
	}
		
	alink_set_shn(hw_channel_parm, len / 4);

}
static void iis_handle_rx1(void *priv, s16 *buf, u16 len)
{
	struct alnk_hw_ch *hw_channel_parm = *(struct alnk_hw_ch **)priv;
    if(hw_channel_parm == NULL)
	{
        return;
    }
	
	if (hw_channel_parm->ch_idx < sizeof(I2sMoudle.iis_cbfn)/sizeof(I2sMoudle.iis_cbfn[0]) &&
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx])
	{
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx](buf, len);
	}

	alink_set_shn(hw_channel_parm, len / 4);
}
#endif

#if UCFG_IIS_CH1_EN
static void iis_handle_tx2(void *priv, s16 *buf, u16 len)
{
	struct alnk_hw_ch *hw_channel_parm = *(struct alnk_hw_ch **)priv;
    if(hw_channel_parm == NULL)
	{
        return;
    }

	if (hw_channel_parm->ch_idx < sizeof(I2sMoudle.iis_cbfn)/sizeof(I2sMoudle.iis_cbfn[0]) &&
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx])
	{
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx](buf, len);
	}

	alink_set_shn(hw_channel_parm, len / 4);
}

static void iis_handle_rx2(void *priv, s16 *buf, u16 len)
{
	struct alnk_hw_ch *hw_channel_parm = *(struct alnk_hw_ch **)priv;
    if(hw_channel_parm == NULL)
	{
        return;
    }

	if (hw_channel_parm->ch_idx < sizeof(I2sMoudle.iis_cbfn)/sizeof(I2sMoudle.iis_cbfn[0]) &&
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx])
	{
		I2sMoudle.iis_cbfn[hw_channel_parm->ch_idx](buf, len);
	}

	alink_set_shn(hw_channel_parm, len / 4);
}
#endif

static void ej_bsp_iis_moudle_init(void)
{
	I2sMoudle.hw_alink = alink_init(&iis_data);
#if UCFG_IIS_CH0_EN
	I2sMoudle.alink_ch[0] =  alink_channel_init(I2sMoudle.hw_alink, 0, ALINK_DIR_TX, (void *)&I2sMoudle.alink_ch[0], iis_handle_tx1);
	I2sMoudle.alink_ch[1] =  alink_channel_init(I2sMoudle.hw_alink, 1, ALINK_DIR_RX, (void *)&I2sMoudle.alink_ch[1], iis_handle_rx1);
#endif

#if UCFG_IIS_CH1_EN
	I2sMoudle.alink_ch[2] =  alink_channel_init(I2sMoudle.hw_alink, 2, ALINK_DIR_TX, (void *)&I2sMoudle.alink_ch[2], iis_handle_tx2);
	I2sMoudle.alink_ch[3] =  alink_channel_init(I2sMoudle.hw_alink, 3, ALINK_DIR_RX, (void *)&I2sMoudle.alink_ch[3], iis_handle_rx2);
#endif

#if defined(TCFG_SYS_CLOCK_FREQ_FIXED) && TCFG_SYS_CLOCK_FREQ_FIXED
	clk_set("sys", FIXED_CLOCK_FREQ);
#endif

	alink_start(I2sMoudle.hw_alink);
}
static void audio_iis_dec_task(void *param)
{
	ej_bsp_iis_moudle_init();

	while(1)
	{
		os_time_dly(1000);
	}

}

/* public function ---------------------------------------------- */

void ej_bsp_iis_init(void)
{
#if !(UCFG_IIS_CH0_EN || UCFG_IIS_CH1_EN)
	return ;
#endif

#if 0
	ej_bsp_iis_moudle_init();
#else
	os_task_create(audio_iis_dec_task, (void *)0, 1, 1024, 0, "iis_dec");
#endif
}

void ej_bsp_iis_datas_cbfn_set(BspI2sCh_e ch,
							iis_datas_cbfn_t tx_cb, iis_datas_cbfn_t rx_cb)
{
#if UCFG_IIS_CH0_EN
	if (ch == BSP_IIS_CH0)
	{
		I2sMoudle.iis_cbfn[0] = tx_cb;
		I2sMoudle.iis_cbfn[1] = rx_cb;
	}
#endif

#if UCFG_IIS_CH1_EN
	if (ch == BSP_IIS_CH1)
	{
		I2sMoudle.iis_cbfn[2] = tx_cb;
		I2sMoudle.iis_cbfn[3] = rx_cb;		
	}
#endif
}

